<template>
    <!-- 封装多张图片上传组件 -->
    <uv-upload width="160rpx" height="160rpx" customStyle="margin-top: 20rpx;" :fileList="fileList" name="upload"
        :accept="accept" :maxCount="mount" :previewFullImage="true" @afterRead="handleAfterRead" @delete="handleDelete"
        @oversize="handleOverSize" :maxSize="imgSizeComputed">
        <view class="upload-add df fdc ac jc">
            <uv-icon name="plus" size="50rpx"></uv-icon>
            <view v-if="mount > 1" class="upload-count">{{ fileList.length }}/{{ mount }}</view>
        </view>
    </uv-upload>
</template>

<script setup lang="ts">
import { SysFileDel_API } from '@/server/home';
import uploadfiles from '@/server/uploadfiles';

defineOptions({ name: "lh-upload-img" })
/**
 * lh-upload-img 多张图片上传组件
 * @description 支持多张图片上传，带进度显示和错误处理
 * @property {String} maxSize 文件大小限制（默认 '2M'）
 * @property {Array<String>} list 回显图片列表
 * @property {Number} mount 最大上传数量（默认 6）
 * @property {String} accept 文件类型（默认 'image'）
 * @property {Object} formData 上传时的额外表单数据
 * @event {Function} change 文件列表变化时触发，返回文件ID数组
 * @example <lh-upload-img :list="formData.fileList" @change="handleChange"></lh-upload-img>
 */
const props = defineProps({
    maxSize: {
        type: String,
        default: "2" // 默认 2M
    },
    list: {
        type: Array,
        default: () => []
    },
    mount: {
        type: Number,
        default: 6
    },
    accept: {
        type: String,
        default: "image"
    },
    formData: {
        type: Object,
        default: () => ({})
    }
})
const emit = defineEmits(["change"])
const fileList = ref([])

// 使用 watchEffect 监听回显列表变化，执行一次后停止
const stopWatcher = watchEffect(() => {
    const val = props.list
    console.log("val:", val);
    if (!val || val.length == 0) return
    if (!Array.isArray(val)) {
        console.error("list 必须是一个数组")
        return
    }
    fileList.value = val.map((url) => ({
        url: import.meta.env.LH_FILE_BASEURLDZFZ + url,
        status: "success"
    }))
    // 在下一个 tick 中停止监听器，避免初始化问题
    nextTick(() => {
        stopWatcher()
    })
})

// 计算图片上传大小限制（字节）
const imgSizeComputed = computed(() => +props.maxSize * 1024 * 1024)
// 删除图片
const handleDelete = async (event) => {
    try {
        const fileName = event.file?.url.split('/').pop()
        if (!fileName) return

        const res = await SysFileDel_API(fileName)
        if (res.IsSuccess) {
            fileList.value.splice(event.index, 1)
            emitChange()
        } else {
            uni.$uv.toast('删除失败，请重试')
        }
    } catch (error) {
        console.error('删除图片失败:', error)
        uni.$uv.toast('删除失败，请重试')
    }
}

// 新增图片上传
const handleAfterRead = async (event) => {
    const file = event.file
    if (!file) return

    // 添加上传中的文件到列表
    const uploadingFile = {
        url: file.url,
        status: "uploading",
        message: "上传中"
    }
    fileList.value.push(uploadingFile)

    const fileIndex = fileList.value.length - 1

    try {
        const result = await uploadFile(file.url)
        if (result) {
            // 上传成功，更新文件状态
            fileList.value[fileIndex] = {
                status: "success",
                url: import.meta.env.LH_FILE_BASEURLDZFZ + result
            }
            emitChange()
        } else {
            // 上传失败，移除文件
            fileList.value.splice(fileIndex, 1)
            uni.$uv.toast('上传失败，请重试')
        }
    } catch (error) {
        // 上传出错，移除文件
        fileList.value.splice(fileIndex, 1)
        console.error('上传失败:', error)
        uni.$uv.toast('上传失败，请重试')
    }
}
// 文件大小超出限制
const handleOverSize = () => {
    const fileType = props.accept === "image" ? "图片" : "视频"
    uni.$uv.toast(`${fileType}大小不能超过${props.maxSize}M`)
}
// 触发文件列表变化事件
const emitChange = () => {
    const fileIds = fileList.value
        .filter(file => file.status === "success")
        .map(file => file.url.split("/").pop())

    emit("change", fileIds)
}

// 上传文件到服务器
const uploadFile = async (fileUrl) => {
    const res = await uploadfiles.uploadImg_API({ file: fileUrl }, props.formData)
    if (res.IsSuccess) {
        return res.Data.Id
    }
    return null
}
</script>

<style lang="scss" scoped>
.upload-add {
    border-radius: 10rpx;
    background: #edf2fa;
    width: 160rpx;
    height: 160rpx;
    border: 1rpx dashed #d1cdcd;
    transition: all 0.3s ease;

    &:active {
        background: #e0e7ff;
        border-color: #9ca3af;
    }
}

.upload-count {
    font-size: 24rpx;
    color: #6b7280;
    margin-top: 8rpx;
}

:deep(.uv-upload__deletable__icon .uv-icon__img) {
    width: 30rpx;
    height: 30rpx;
}
</style>
